package twinb.text;

import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

public class TermVector
{
    List<Set<String>>          	diction 			= null;

    private Map<String, Double> vec    				= new HashMap<String, Double>();
    
    public double 				len				   	= 0.0;
    
    Map<String, Integer> 		tf 					= new HashMap<String, Integer>(), 
    							df = new HashMap<String, Integer>();

    public TermVector(List<Set<String>> diction)
    {
        this.diction = diction;
    }

    public TermVector()
    {

    }
    
    public void updateLen()
    {
    	len=0.0;
    	for (String key : this.vec.keySet())
        	len += vec.get(key) * vec.get(key);
        
        len = Math.sqrt(len);

    }
    
    public void setVector(Map<String, Double> vec)
    {
    	this.vec=vec;
    	this.updateLen();
    }

    public void clear()
    {
        vec.clear();
    }
/*
    public void addDoc(List<String> bag)
    {
        diction.add(new HashSet<String>());
        Set<String> doc = diction.get(diction.size() - 1);
        for (int i = 0; i < bag.size(); ++i)
            doc.add(bag.get(i));
    }
*/
    public int getDf(String word)
    {
        int ans = 0;
        for (int i = 0; i < diction.size(); ++i)
            if (diction.get(i).contains(word))
                ++ans;
        return ans;
    }

    public void addTerms(List<String> bag)
    {
        
        for (int i = 0; i < bag.size(); ++i)
        {
            String word = bag.get(i);
            if (tf.containsKey(word))
            {
                tf.put(word, tf.get(word) + 1);
            }
            else
            {
                tf.put(word, 1);
                df.put(word, this.getDf(word));
            }

        }
        double N = diction.size();

        for (String key : tf.keySet())
        {
            vec.put(key, (1.0 + Math.log(tf.get(key))) * (N / df.get(key)));
        }
        
        this.updateLen();
    }
    
    public Map<String, Double> getVec()
    {
    	return this.vec;
    }

    public void setSearchSpace(List<String> bag)
    {
        Map<String, Integer> tf = new HashMap<String, Integer>();
        for (int i = 0; i < bag.size(); ++i)
        {
            String word = bag.get(i);
            if (tf.containsKey(word))
            {
                tf.put(word, tf.get(word) + 1);
            }
            else
            {
                tf.put(word, 1);
            }

        }
        double len = 0.0;
        vec.clear();
        for (String key : tf.keySet())
        {
            vec.put(key, (1.0 + Math.log(tf.get(key))));
            len += vec.get(key) * vec.get(key);
        }
        len = Math.sqrt(len);
        
    }
    
    public double getLen()
    {
    	this.updateLen();
    	if(this.len==0)
    	{
    		System.out.println("Error: vector length = 0");
    		return 1.0;
    	}
    	else
    		return this.len;
    }

    public double cos(TermVector vecU)
    {
        double ans = 0;
        Map<String, Double> uec = vecU.vec, temp = null;
        if (uec.size() < vec.size())
        {
            temp = uec;
            uec = vec;
            vec = temp;
        }

        for (String key : vec.keySet())
            if (uec.containsKey(key))
                ans += vec.get(key) * uec.get(key);

        return ans/this.getLen()/vecU.getLen();
    }
}
